package org.kernely.stream.administration;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.kernely.security.dao.GroupDAO;
import org.kernely.security.dao.PermissionDAO;
import org.kernely.security.persistence.Group;
import org.kernely.security.persistence.Permission;
import org.kernely.security.persistence.User;
import org.kernely.stream.persistence.Stream;
import org.kernely.ui.mvp.KernelyPresenter;

import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;

public class StreamGroupRightsPresenter extends KernelyPresenter<StreamGroupRightsView>{


	/**
	 * The Stream to edit in edition mode
	 */
	private Stream stream;
	private boolean editMode = false;
	/**
	 * Available users for this stream
	 */
	private Set<Group> selectableGroups;
	/**
	 * Already selected users for this stream
	 */
	private Map<Group, Integer> selectedGroups;

	/**
	 * Groups which rights have been removed
	 */
	private Set<Group> removedGroups;

	
	public StreamGroupRightsPresenter(){

	}

	public StreamGroupRightsPresenter(Stream s){
		this.stream = s;
		this.editMode = true;
	}

	@Override
	public final void bind() {
		GroupDAO gdao = GroupDAO.getInstance();
		selectedGroups = new HashMap<Group, Integer>();
		selectableGroups = new HashSet<Group>(gdao.getAllGroups());
		removedGroups = new HashSet<Group>();
		
		// In edition mode, fill the fields with the informations
		if(stream != null && editMode){
			// Select all the permissions linked to the resource
			Set<Permission> perms = PermissionDAO.getInstance().findPermissionByResourceID(stream.getUid());
			if (perms == null){
				perms = new HashSet<Permission>();
			}

			for(Permission p : perms){
				// Add the groups with subscribe, write and delete rights
				if(p.getRights().equals(StreamManagementWindowPresenter.SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING)){
					for(Group g : p.getGroups()){
						fillSelectedGroups(g, StreamUserRightsView.DELETE_RIGHT);
						// We remove the user in selectableUsers list
						selectableGroups.remove(g);
					}
				}
				// Add the groups with subscribe and write rights
				else if(p.getRights().equals(StreamManagementWindowPresenter.SUBSCRIPTION_REDACTION_RIGHTS_STRING)){
					for(Group g : p.getGroups()){
						fillSelectedGroups(g, StreamUserRightsView.REDACTION_RIGHT);
						// We remove the user in selectableUsers list
						selectableGroups.remove(g);
					}
				}
				// Add the groups with subscribe rights
				else{
					for(Group g : p.getGroups()){
						fillSelectedGroups(g, StreamUserRightsView.SUBSCRIPTION_RIGHT);
						// We remove the user in selectableUsers list
						selectableGroups.remove(g);
					}
				}
			}
		}

		lists();


		// Add a listener to the add button
		this.view.getAddButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -115612811698526312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				addGroup();
			}
		});

		// Add a listener to the delete button
		this.view.getDeleteButton().addListener(new Button.ClickListener() {
			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				removeGroup();
			}
		});
	}

	/**
	 * Adds a new user in the selected groups list for this stream
	 */
	protected final void addGroup() {
		GroupDAO gdao = GroupDAO.getInstance();
		int groupID = (Integer) this.view.getGroupsBox().getValue();
		Group group = gdao.getGroupById(groupID);
		selectableGroups.remove(group);
		selectedGroups.put(group, StreamUserRightsView.SUBSCRIPTION_RIGHT);
		removedGroups.remove(group);
		//Actualize lists
		lists();
	}

	/**
	 * Remove a group from the selected groups list for this stream
	 */
	protected final void removeGroup() {
		GroupDAO gdao = GroupDAO.getInstance();
		Collection<Integer> removedGroupID = (Collection<Integer>)this.view.getTable().getValue();
		for (Integer groupID : removedGroupID){
			Group group = gdao.getGroupById(groupID);
			selectableGroups.add(group);
			selectedGroups.remove(group);
			removedGroups.add(group);
		}
		//Actualize lists
		lists();
	}

	/**
	 * Lists the selectable users in the combo box and the group users in the list.
	 */
	private final void lists(){

		// Remove all items
		this.view.getGroupsBox().removeAllItems();
		this.view.getTable().removeAllItems();

		//List the group users
		for(Entry<Group, Integer> e : selectedGroups.entrySet()){
			Group g = e.getKey();
			// Display user in the group's users list
			this.view.getTable().addItem(new Object[] {g.getName(), e.getValue()}, g.getId());
		}

		// List selectable users
		for(Group g : selectableGroups){
			this.view.getGroupsBox().addItem(g.getId());
			this.view.getGroupsBox().setItemCaption(g.getId(),g.getName());
		}
	}

	/**
	 * Add the groups in the list of user who have rights on the stream.
	 * If the group was in the list with a right inferior or equal,
	 * the new right is set.
	 * @param g The group
	 * @param permission The permission (subscribe, write or delete messages)
	 */
	private final void fillSelectedGroups(Group group, int permission){
		Integer actualValue = selectedGroups.get(group);
		if (actualValue == null || actualValue < permission){
			selectedGroups.put(group, permission);
		}
		
	}
	
	/**
	 * Gets the removed groups, i.e. groups that have no more rights on the stream
	 * @return the removed groups
	 */
	public final Set<Group> getRemovedGroups() {
		return removedGroups;
	}
	
}
